package com.game.logic.items;

import akka.actor.ActorRef;
import com.coment.cfg.luban.Tables;
import com.coment.cfg.luban.constant.ItemsType;
import com.coment.cfg.luban.items.DongFuCfg;
import com.coment.game.config.ConfigException;
import com.coment.message.DrawResult;
import com.coment.message.account.ReceiveInfo;
import com.coment.message.roles.Equip;
import com.coment.message.roles.ObtainExp;
import com.coment.po.UserDongFu;
import com.coment.po.UserPet;
import com.coment.po.UserProp;
import com.coment.po.roles.Roles;
import com.game.dao.user.UserPlayInfoDao;
import com.game.framework.ActorManager;
import com.game.logic.core.comment.Bonus;
import com.game.logic.fighting.actor.RolesActor;
import com.game.logic.items.account.UserAccountActor;
import com.game.logic.items.bonus.BonusService;
import com.game.logic.items.dongFu.UserDongFuService;
import com.game.logic.items.pet.PetService;
import com.game.logic.items.prop.PropService;
import com.game.logic.roles.RolesService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/// ALL:物品服务
@Slf4j
@Service
public class ItemsService {
    @Resource
    private UserPlayInfoDao userPlayInfoDao;

    @Resource
    private RolesService rolesService;
    public static List<Integer> itemTypes = List.of(
            ItemsType.Currency,
            ItemsType.Equip,
            ItemsType.Pet,
            ItemsType.House,
            ItemsType.card,
            ItemsType.exp
    );
    @Resource
    private PetService petService;
    @Resource
    private PropService propService;
    @Resource
    private UserDongFuService userDongFuService;

    /// 获取物品
    public List<DrawResult> obtainItems(
            Integer userInfoId,
            int itemsType,
            Integer value
    ) {
        List<DrawResult> drawResults = obtainRewards(userInfoId, itemsType, value);
        issueRewards(userInfoId, drawResults);
        return drawResults;
    }

    public static List<DrawResult> obtainRewards(Integer userInfoId, int itemsType, Integer value) {
        List<DrawResult> res = new ArrayList<>();
        // 礼包
        if (itemsType == ItemsType.Bonus) {
            Bonus<Integer> integerBonus = BonusService.bonusPoll.get(value);

            if (Optional.ofNullable(integerBonus).isEmpty()) {
                throw new ConfigException("配表异常未找到礼包" + value);
            }

            log.debug("获取{}- {} 礼包", value, integerBonus);
            int group = integerBonus.getGroup();
            List<Integer> bonusValue = integerBonus.getBonusValue();
            for (Integer integer : bonusValue) {
                List<DrawResult> results = obtainRewards(
                        userInfoId,
                        group,
                        integer
                );
                res.addAll(results);
            }
        }

        // 普通
        if (itemTypes.contains(itemsType)) {
            DrawResult result = new DrawResult();
            result.setUserInfoId(userInfoId);
            result.setType(itemsType);
            result.setValue(value);
            res.add(result);
        }
        return res;
    }

    @Async
    public void issueRewards(Integer userInfoId, List<DrawResult> drawResults) {
        String recentlyPlayedRolesId = userPlayInfoDao.findByUserInfoIdOrCreate(userInfoId).getRecentlyPlayedRolesId();
        for (DrawResult drawResult : drawResults) {
            int itemsType = drawResult.getType();
            Integer value = drawResult.getValue();
            switch (itemsType) {
                case ItemsType.Currency:
                    log.debug("获取 {} 货币", value);
                    break;
                case ItemsType.Equip:
                    log.debug("获取 {} 装备", value);
                    RolesActor.getRolesActor(recentlyPlayedRolesId).tell(new Equip(recentlyPlayedRolesId, value, 1), ActorRef.noSender());
                    break;
                case ItemsType.Pet:
                    UserPet pet = petService.tryObtainPet(userInfoId, value);
                    log.debug("获取 {} 宠物", pet);
                    break;
                case ItemsType.House:
                    UserDongFu userDongFu = userDongFuService.get(userInfoId);
                    DongFuCfg obtain = Tables.cfg.get_tbdongfucfg().get(value);
                    Integer userDongFuDongFuId = userDongFu.getDongFuId();
                    if (userDongFuDongFuId < obtain.id) {
                        userDongFuService.replaceDongFu(userInfoId, userDongFu, obtain);
                    }
                    log.debug("获取 {} DongFuAction", userDongFu);
                    break;
                case ItemsType.Prop:
                    UserProp userProp = propService.obtainOrUpgrade(userInfoId, value);
                    log.debug("获取 {} 道具", userProp);
                    break;
                case ItemsType.card:
                    Roles roles = this.rolesService.tryObtainRoles(userInfoId, value);
                    log.debug("获取 {} 角色", roles);
                    break;
                case ItemsType.exp:
                    ActorManager.getActor(RolesActor.class, recentlyPlayedRolesId).tell(
                            new ObtainExp((double) value),
                            ActorRef.noSender()
                    );
                    break;
                default:
            }
        }
    }

    public record ObtainItem(
            int itemType,
            int itemId,
            int itemCount
    ) {
    }

    public void doObtainItem(Integer[] userInfoIds, List<ObtainItem> obtainItemList) {
        for (Integer userInfoId : userInfoIds) {
            try {
                doObtainItem(userInfoId, obtainItemList);
            } catch (Exception e) {
                log.error("获取物品异常", e);
            }
        }
    }

    public void doObtainItem(Integer userInfoId, List<ObtainItem> obtainItemList) {
        String recentlyPlayedRolesId = userPlayInfoDao.findByUserInfoIdOrCreate(userInfoId).getRecentlyPlayedRolesId();
        for (ObtainItem obtainItem : obtainItemList) {
            try {
                doObtainItem(userInfoId, obtainItem, recentlyPlayedRolesId);
            } catch (Exception e) {
                log.error("获取物品异常", e);
            }
        }
    }

    private void doObtainItem(Integer userInfoId, ObtainItem obtainItem, String recentlyPlayedRolesId) {
        int itemType = obtainItem.itemType;
        int itemId = obtainItem.itemId;
        int itemCount = obtainItem.itemCount;
        switch (itemType) {
            case ItemsType.Currency:
                ActorManager.getActor(
                        UserAccountActor.class,
                        userInfoId
                ).tell(
                        new ReceiveInfo(userInfoId, itemId, itemCount, ""),
                        ActorRef.noSender()
                );
                break;
            case ItemsType.Equip:
                RolesActor.getRolesActor(recentlyPlayedRolesId).tell(new Equip(recentlyPlayedRolesId, itemId, itemCount), ActorRef.noSender());
                break;
            case ItemsType.Pet:
                UserPet pet = petService.tryObtainPet(userInfoId, itemId);
                break;
            case ItemsType.House:
                UserDongFu userDongFu = userDongFuService.get(userInfoId);
                DongFuCfg obtain = Tables.cfg.get_tbdongfucfg().get(itemId);
                Integer userDongFuDongFuId = userDongFu.getDongFuId();
                if (userDongFuDongFuId < obtain.id) {
                    userDongFuService.replaceDongFu(userInfoId, userDongFu, obtain);
                }
                break;
            case ItemsType.Prop:
                UserProp userProp = propService.obtainOrUpgrade(userInfoId, itemId);
                break;
            case ItemsType.card:
                for (int i = 0; i < itemCount; i++) {
                    rolesService.tryObtainRoles(userInfoId, itemId);
                }
                break;
            case ItemsType.exp:
                ActorManager.getActor(RolesActor.class, recentlyPlayedRolesId).tell(
                        new ObtainExp((double) itemId),
                        ActorRef.noSender()
                );
                break;
            default:
        }
    }
}
